/*
 【基础】求 1! + 2! + 3! + 4! + ... + n!
  题目描述
    请求出 1! + 2! + 3! + 4! + ... + n!，请注意，n <= 50。
      n! = n * (n - 1) * (n - 2) * ... * 1，如：5! = 5 * 4 * 3 * 2 * 1 = 120。
  输入
    请输入一个整数 n（n <= 50）
  输出
    输出求和的结果
  样例输入
    10
  样例输出
    4037913
*/

#include <bits/stdc++.h>
using namespace std;

/*
  说明: 本文的代码实现中，高精度乘法和加法的代码实现为什么要用全局变量?
  解答: 在乔斯 OJ 上，最开始使用局部变量，但是 OJ 提示出现栈溢出，
        所以才在对应的代码实现中, 将局部变量改用成用全局变量!
*/
string a, b = "1"; // 在f()函数中，进行高精度乘法计算的 2 个乘数: a 和 b
string numi;
int a1, b1;
string ai = "0";
/*
  注意 !!!
    全局变量的大小的评估思路:
      当 n 取最大值 50 时, n! 展开(1 * 2 * ... * n) 后, 我们可以发现共有 9 个个位数相乘、41 个 2 位数相乘，
      那么 n! 的结果(10 进制) 最大可能有 9 + 41 * 2 = 9 + 82 个位！
    参考:
      1 个 2 位数(10 进制) 乘以 3 位数(10 进制)，最后的乘积(10 进制)最大可能有 2 + 3 = 5 位
      1 个 m 位数(10 进制) 乘以 n 位数(10 进制)，最后的乘积(10 进制)最大可能有 m + n 位
*/
int num[40212] = {}; // 该全局变量用于存放"高精度乘法"和"高精度加法"的中间计算结果。
                     // 注意: 由于是全局变量, 每次进行计算前要对该变量清零,
                     //       才能保证高精度乘法和高精度加法的计算结果的正确性!

/*
  该函数计算 2 个高精度数相加的结果。
    这 2 个高精度数如下:
      "string 类型的全局变量 numi 表示的 10 进制数"
      "string 类型的全局变量 ai 表示的 10 进制数"
    相加后的结果保存在 string 类型的全局变量 ai 中
*/
void an() {
    // 1. 对位
    //      (保证相乘的 2 个字符串位数相同)
    while (numi.size() > ai.size()) {
        ai = '0' + ai;
    }
    while (numi.size() < ai.size()) {
        numi = '0' + numi;
    }

    // 2. 倒序相加 (考虑进位问题)
    int jw = 0; // 进位
    string c;   // 局部变量，存放 "2 个高精度数相加后得到的结果" 对应的字符串
    for (int i = ai.size() - 1; i >= 0; i--) {
        int a1 = ai[i] - '0', b1 = numi[i] - '0';
        int xi = (a1 + b1 + jw) % 10;
        char xi1 = xi + '0';
        c = xi1 + c;
        jw = (a1 + b1 + jw) / 10;
    }

    // 3. 清除多余的前导 '0'
    while (c.size() > 1 && c[0] == '0') {
        c.erase(0, 1); // 清除字符串 c 最左边的 1 个字符
    }

    // 4. 处理进位 (如果需要进位, 则在表示结果的字符串 c 的左边补 '1')
    if (jw != 0) {
        c = '1' + c;
    }

    // 将加法的结果保存到 string 类型的全局变量 ai 中
    ai = c;
}

/*
  该函数计算 2 个高精度数相乘的结果。
    这 2 个高精度数如下:
      "string 类型的全局变量 a 表示的 10 进制数"
      "string 类型的全局变量 b 表示的 10 进制数"
    相加后的结果保存在 string类型的全局变量 numi 中
*/
void f() {
    // 初始化 "全局数组 num", 并且清空 "string 类型的全局变量 numi"
    // 注意: 由于在进行高精度计算时会用到这 2 个全局变量，
    //       为保证计算的正确性，我们需要对全局变量进行初始化!
    for (int i = 0; i < 40212; i++) {
        num[i] = 0;
    }
    numi.clear();

    // 1. 计算乘法的积每位上的数（不算进位）
    for (int i = 0; i < a.size(); i++) {
        for (int j = 0; j < b.size(); j++) {
            a1 = a[i] - '0';
            b1 = b[j] - '0';
            num[i + j + 1] = num[i + j + 1] + a1 * b1;
        }
    }

    // 2. 处理进位
    for (int i = a.size() + b.size() - 1; i >= 1; i--) {
        num[i - 1] += num[i] / 10;
        num[i] %= 10;
    }

    // 3. 累加(将乘法的积转换成 string）
    for (int i = a.size() + b.size() - 1; i >= 0; i--) {
        numi = char(num[i] + '0') + numi;
    }

    // 4. 去除前导零
    while (numi.size() > 1 && numi[0] == '0') {
        numi.erase(0, 1);
    }
}

int main() {
    int n;

    cin >> n;

    // 注意: n 的取值范围，考虑边界值！
    //       题目说明中未提到不等于 0，因此我们在编码时要考虑 n 为 0 的情况!
    //       另外，需要注意数学知识点: 0! 等于 1
    if (n == 0) {
        cout << 1;
        return 0;
    }

    for (int i = 1; i <= n; i++) {
        /*
          思路: 在每轮循环中，先计算 !i 的值，然后将得到的值进行累加求和
        */
        int j = i;

        // 对于 整形数 j，计算得到其对应的字符串 a
        while (j != 0) {
            a = char(j % 10 + '0') + a;
            j = j / 10;
        }

        /*
          调用函数 f(), 对于 string 类型的全局变量 a 和 b，进行高精度乘法计算，
          并将计算结果保存在 string 的类型全局变量 numi 中。
        */
        f();
        b.clear();
        b = numi;  // 乘法的结果保存到 string 类型的全局变量 b 中
        a.clear(); // 下一轮计算的时候，会用到字符串 a，这里先进行清空动作，避免影响下一轮计算的结果

        /*
          调用函数 an(), 对于 string 类型的全局变量 numi 和 ai，进行高精度加法计算，
          并将计算结果保存在 string 的类型全局变量 ai 中。
        */
        an();
    }
    cout << ai;

    return 0;
}